package auser;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;

import org.apache.commons.beanutils.locale.LocaleBeanUtils;

import com.db4o.CountedObject;
import com.db4o.Db4oUtil;
import com.db4o.IncrementedId;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.events.Event4;
import com.db4o.events.EventListener4;
import com.db4o.events.EventRegistry;
import com.db4o.events.EventRegistryFactory;
import com.db4o.events.ObjectEventArgs;
import com.db4o.events.EventArgs;
import com.db4o.ext.ExtObjectContainer;
import com.db4o.query.Query;
import com.db4o.servlet.Db4oServlet;
import com.spaceprogram.db4o.sql.Sql4o;
import com.spaceprogram.db4o.sql.Sql4oException;
import com.spaceprogram.db4o.sql.parser.SqlParseException;

import facades.SqlResultList;
 
public class Db4oCareTaker {
	private ExtObjectContainer container = null; 
	
	public static void registerCallback(final ObjectContainer db){
		EventRegistry registry =  EventRegistryFactory.forObjectContainer(db);
		// register an event handler, which will assign autoincremented IDs to any
		// object extending CountedObject, when the object is created
		
		registry.creating().addListener(new EventListener4() {
			public void onEvent(Event4 e, EventArgs args) {
				ObjectEventArgs queryArgs = ((ObjectEventArgs) args);
				Object obj = queryArgs.object();
				// only for the objects extending the CountedObject
				if (obj instanceof CountedObject){
					try{
						if(((CountedObject)obj).getId()==0)((CountedObject)obj).setId(getNextId(db));
					}catch(Exception e1){
						e1.printStackTrace();
					}
				}
				
				
			}
		});
		
		registry.updated().addListener(new EventListener4() {
			public void onEvent(Event4 e, EventArgs args) {
				ObjectEventArgs queryArgs = ((ObjectEventArgs) args);
				Object obj = queryArgs.object();
				// only for the objects extending the CountedObject
				try{
					if(((CountedObject)obj).getId()==0)((CountedObject)obj).setId(getNextId(db));
				}catch(Exception e1){
					e1.printStackTrace();
				}
			}
		});
		
		 
		
	}
	// end registerCallback

	private static long getNextId(ObjectContainer db) {
		// this function retrieves the next available ID from 
		// the IncrementedId object
		IncrementedId r = IncrementedId.getIdObject(db); 	
		long nRoll;
		nRoll = r.getNextID(db);
		
		return nRoll;
	}
	// end getNextId
	
	public Db4oCareTaker (ExtObjectContainer cont){
		container=cont;
		//registerCallback(container);
	}
	
	public Db4oCareTaker (HttpSession session,String dbName){
		container = (ExtObjectContainer)Db4oServlet.sharedTransaction(
				session.getServletContext(),
				session,
				dbName
		);
		//registerCallback(container);
	}
	
	
	public void setBean(Object bean,Map properties){
		try {
			LocaleBeanUtils.populate(bean,properties);		
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
	}
	
	 
	public ExtObjectContainer getContainer(){
		return container;
	}

	public long getID(Object obj){
		return container.getID(obj);
	}
	
	public long getID(String name,PageContext context){
		return container.getID(context.getAttribute(name));
	}
	 
	public Object getById(long id){
		return container.getByID(id);
	}
	
	public Object getById(String id){
		return container.getByID(new Long(id));
	}
	
	public Query newQuery(Class clazz){
		Query qu = container.query();
		qu.constrain(clazz);
		return qu;
		
	}
	
	public ObjectSet get(Object object){
		return container.get(object);
	}
	
	public Object getFirst(Object object){
		ObjectSet r =container.get(object);
		if(r.isEmpty()) return null;
		return r.get(0);
	}
	
	public ObjectSet getByMap(Map map,Object emptyPrototype){
		setBean(emptyPrototype,map);
		return container.get(emptyPrototype);
	}
	
	public boolean objectIsCopy(Map values,Object emptyPrototype,Object original){
		ObjectSet objects = getByMap(values,emptyPrototype);
		if(objects.size()<=0) return false;
		
		return !objects.contains(original);
	}
	
	public boolean objectIsCopy(Object prototype,Object original){
		ObjectSet objects = get(prototype);
		if(objects.size()<=0) return false;
		
		return !objects.contains(original);
	}
	
	public void set(Object object){ 
		try{
			container.set(object);
			container.commit();
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
	
	public void set(Object object,int i){
		
		try{
			container.set(object,i); 
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public List querySql(String sql){
		SqlResultList l = null;
		try {
			l = new SqlResultList( Sql4o.execute(container, sql));
		} catch (SqlParseException e) { 
			//e.printStackTrace();
		} catch (Sql4oException e) { 
			//e.printStackTrace();
		}
		return l;
	}
	
	public Object objectFromSql(String sql){
		SqlResultList l = null;
		
		try {
			return new SqlResultList( Sql4o.execute(container, sql)).get(0);
		} catch (Exception e) { 
			//e.printStackTrace();
			return null;
		}

	}
	
	public List querySql(String className,String where,String orderBy){
		if(where!=null) where = " WHERE " + where;
		
		if(orderBy==null) orderBy="";
		else orderBy=" ORDER BY " + orderBy;
		
		String sql = 	" SELECT * FROM " + className + " o " +
						where +
						orderBy;
		
		return querySql(sql);
	}
	
}
